using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Framework.Core.Io;

namespace Framework.Core.Process.Tasks
{
    internal struct Handle : ICommand, IProcessTask<IEnumerable<IProcess>>
    {
        private const string HandleExePath = @"handle.exe";
        private static readonly string HandleExeName = Path.GetFileNameWithoutExtension(HandleExePath);

        private static readonly Regex HandleRegex = new Regex(@"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)", RegexOptions.Compiled | RegexOptions.CultureInvariant);

        static Handle()
        {
            HandleExePath.Deploy();
        }

        public Handle(string path)
            : this()
        {
            Name = HandleExeName;
            FileName = HandleExePath;
            Arguments = string.Format(@"-accepteula {0}", path);
        }

        public string Name { get; private set; }
        public string FileName { get; private set; }
        public string Arguments { get; private set; }
        public bool IsNative { get { return false; } }

        public IEnumerable<IProcess> Execute(IProcessRunner processRunner)
        {
            var excludedPids = new List<int> { -1, -2, 4 };
            var processResult = processRunner.Start(this);

            if (processResult.StandardOutput.IndexOf("Initialization error", StringComparison.InvariantCultureIgnoreCase) >= 0)
            {
                throw new ProcessResultException(processResult);
            }

            var handlePids =
                HandleRegex.Matches(processResult.StandardOutput)
                     .Cast<Match>()
                     .Select(m => int.Parse(m.Value))
                     .Except(excludedPids)
                     .ToList();

            return new TaskList().Execute(processRunner).Where(p => handlePids.Any(hp => hp == p.ProcessId));
        }
    }
}